<?php
namespace common\widgets;

use Yii;
use yii\helpers\Html;
use yii\helpers\ArrayHelper;

/**
 * 改造DetailView，支持一行显示多个字段
 * 使用 fieldRows 属性代替 attributes 进行字段设置，fieldRows 为二维数组，
 * 每个元素数组表示一行，元素数组里用 label=>value 表示标题和数据值,
 * 'fieldRows' => [
 *      [
 *          'label1' => 'value1',
 *          'label2' => 'value2',
 *      ],
 *      [
 *          'label3' => 'value3',
 *          'label4' => 'value4',
 *      ],
 *  ],
 *  
 * 在 label 后面可附加选项，格式如： label:fmt、label:l.v或label:fmt:l.v
 *  fmt     指定输出格式，如'date'、'text'、'html'、'raw'等，
 *          用于 yii\i18n\Formatter::format() 对 value 进行格式化，
 *          不指定 fmt 时，默认使用 Html::encode() 进行编码输出
 *  l.v     数字l表示 lebel 要占的列数，数字v表示 value 要占的列数，
 *          不带点只指定一个数字时，表示省略l，仅指定v，
 *          只指定一个数字后面带点，表示仅指定l，省略v
 */
class DetailView extends \yii\widgets\DetailView
{
    public $fieldRows;
    
    public $fieldTemplate = '<th{labelOptions}>{label}</th><td{valueOptions}>{value}</td>';
    
    public $options = ['class' => 'table table-bordered detail-view'];

    // label、label:3、label:1.3、label:fmt、label:fmt:3、label:fmt:1.3
    public $labelPattern = '/^(.+?)(?::([a-z]+))?(?::(?:(\d)\.)?(\d)?)?$/';
    
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $rows = [];
        $i = 0;
        foreach ($this->fieldRows as $fieldRows) {
            $row = '<tr>';
            foreach($fieldRows as $label=>$value){
                $row .= $this->renderField($label, $value);
            }
            $row .= '</tr>';
            $rows[] = $row;
        }

        $options = $this->options;
        $tag = ArrayHelper::remove($options, 'tag', 'table');
        echo Html::tag($tag, implode("\n", $rows), $options);
    }

    protected function renderField($label, $value){
        if(preg_match($this->labelPattern, $label, $match)){
            list($txt, $label, $fmt, $l, $v) = $match;
        }
        return strtr($this->fieldTemplate, [
            '{label}' => $label,
            '{value}' => $fmt ? Yii::$app->formatter->format($value, $fmt) : Html::encode($value),
            '{labelOptions}' => $l ? " colspan=\"$l\"" : '',
            '{valueOptions}' => $v ? " colspan=\"$v\"" : '',
        ]);
    }
}
